/*******************************************************************************
 * CopyRight (c) 2020 
 *
 * \file    format.h
 * \brief   Get file format, mp4 and mkv support only
 * \author  ZhangJing
 * \version 1.0.0
 * \date    2020-06-22
 *
 * -----------------------------------------------------------------------------
 *
 * -----------------------------------------------------------------------------
 * Modify History：
 * <Date>       | <Version> | <Author>  | <Discribe>
 * 2020-06-22   | v1.0.0    | ZhangJing | Create file
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#ifndef _FORMAT__H
#define _FORMAT__H

#include <stdio.h>
#include "mp4.h"
#include "mkv.h"

#define PROBE_DATA_MAXSIZE (1024 * 2)

enum {
    ID_MP4,
    ID_MKV,
    ID_MP3,
    ID_AAC,
    ID_H264,
    ID_HEVC
};

typedef struct IOContext {
    const char *filename;
    unsigned char *buffer;  /**< Start of the buffer. */
    int buffer_size;        /**< Maximum buffer size */
    unsigned char *buf_ptr; /**< Current position in the buffer */
    unsigned char *buf_end; /**< End of the data, may be less than buffer+buffer_size */
    long filesize;          /**< max filesize, used to limit allocations */
    long pos;               /**< position in the file of the current buffer */
    int fd;                 /**< file fd */
    FILE *fh;               /**< file handle */
    int (*io_open)(struct IOContext *h, const char *name, char *flags);
    int (*io_read)(struct IOContext *h, void *buf, unsigned int size);
    int (*io_write)(struct IOContext *h, const unsigned char *buf, int size);
    long (*io_seek)(struct IOContext *h, long pos, int whence);
    int (*io_close)(struct IOContext *h);
    long (*io_get_len)(struct IOContext *h);
    long (*io_tell)(struct IOContext *h);
} IOContext;

typedef struct Format {
    const char *formatname;
    int id;             /**< format type id */
    int (*read_probe)(void *format_context);/**< get format name */
    int (*read_header)(void *format_context); /**< get format info */
    int (*read_packet)(void *format_context); /**< get format data */
} Format;

typedef struct BitStreamFilter {
    const char *bsfname;
    int id;
    int (*filter)(void *h, char *ibuf, int ilen, char *obuf, int *olen);
} BitStreamFilter;

typedef struct OutputFormat {
    const char *output_format_name;
    int id;
    int (*write_header)(void *format_context);
    int (*write_packet)(void *format_context);
    int (*write_trailer)(void *format_context);
} OutputFormat;

typedef struct Stream {
    const char *streamname; /**< stream type name */
    int id;                 /**< stream type id */
    int index;              /**< index of streams */
    Mp4Stream *mp4st;
    MkvStream *mkvst;
    BitStreamFilter *bsf;   /**< bit stream filter of stream */
    OutputFormat *ofm;      /**< output format parser */
    int track_type;         /**< 1: video, 2: audio */
} Stream;

typedef struct FormatContext {
    IOContext *io;      /**< file data and interface function */
    char *ofname;       /**< output video file name */ //FIXME:
    char *ofname_audio;  /**< output audio file name */
    unsigned int probe_data_len;
    char *probe_data;   /**< data used for format probe */
    Format *fm;         /**< the format used */
    int nb_streams;     /**< number of streams*/
    Stream **streams;   /**< stream */
    int state;          /**< 0: read header, 1: read packet */
} FormatContext;

extern IOContext io_buffer;
extern IOContext io_file;
extern Format format_mp4;
extern Format format_mkv;

extern OutputFormat mp4_output_format;
extern OutputFormat mkv_output_format;

extern BitStreamFilter h264_mp4toannexb_bsf;
extern BitStreamFilter hevc_mp4toannexb_bsf;
extern BitStreamFilter adts_bsf;

#endif /* _FORMAT__H */
